<?php

class Vega_Cache_Output
{

    /**
     * Vega_Cache_Engine_Abstract object
     *
     * @var Vega_Cache_Engine_Abstract
     */
    protected $_engine = null;


    /**
     * Cache key name prefix
     *
     * @var string
     */
    protected $_prefix = '';

    /**
     * Write log
     *
     * @var array
     */
    protected $_logs = array();


    public function  __construct(Vega_Cache_Engine_Abstract $engine = null)
    {
        if (null === $engine)
        {
            $engine = $this->initDefaultCacheEngine(array());
        }
        $this->_engine = $engine;
    }

    /**
     * Init the default Cache Engine
     *
     */
    public function initDefaultCacheEngine($options = array())
    {
        require_once 'Vega/Cache/Engine/File.php';

        $app = Vega_App::getInstance();

        if (empty($options))
        {
            $options = array('cache_dir' => $app->getRootPath() . DIRECTORY_SEPARATOR . 'cache' .
                DIRECTORY_SEPARATOR . $app->getAppName() . DIRECTORY_SEPARATOR . 'html', 'lifetime' => 15, 'index_level' => 2);
        }
        $engine = new Vega_Cache_Engine_File($options);

        return $engine;
    }

    /**
     * Sets the cache engine
     *
     * @param Vega_Cache_Engine_Abstract $engine
     * @return Vega_Cache_Output
     */
    public function setCacheEngine(Vega_Cache_Engine_Abstract $engine)
    {
        $this->_engine = $engine;
        return $this;
    }

    /**
     * Returns cache key name prefix
     *
     * @return string
     */
    public function getPrefix()
    {
        return $this->_prefix;
    }

    /**
     * Set cache key name prefix
     *
     * @param string $prefix
     * @return Vega_Cache_Output
     */
    public function setPrefix($prefix)
    {
        $this->_prefix = $prefix;
        return $this;
    }

    /**
     * Generate cache ID
     *
     * @param string $name
     * @return string
     */
    protected function _generateId($name, $prefix = null)
    {
        $name = "$name";
        if (!isset ($name[0]))
        {
            require_once 'Vega/Cache/Exception.php';
            throw new Vega_Cache_Exception('Cache name must not be null');
        }

        if ($prefix === null)
        {
            $prefix = $this->_prefix;
        }

        // in case $name is a url
        // strip the first /
        if ($name[0] == '/')
        {
            $name = substr($name, 1);
        }

        $name = str_replace('_', '__', $name);
        $name = str_replace('/', '_', $name);

        return $prefix . $name;
    }

    /**
     * Loads :)
     *
     * @param string $name
     * @param string $prefix
     * @return mixed
     */
    public function load($name, $outputOnly = false, $prefix = null)
    {
        if (null === $this->_engine)
        {
            $this->setCacheEngine();
        }
        $id = $this->_generateId($name, $prefix);

        $cache = $this->_engine->load($id);

        if (!$outputOnly)
        {
            return $cache;
        }
        return $cache['output'];
    }

    /**
     * Saves :)
     *
     * @param string $name
     * @param string $data
     * @param integer $lifetime
     * @param string $prefix
     * @return mixed
     */
    public function save($name, $data, $lifetime, $options = array(), $prefix = null)
    {
        if (null === $this->_engine)
        {
            $this->setCacheEngine();
        }
        $id = $this->_generateId($name, $prefix);

        $this->log($name, $id, $lifetime, strlen($data));

        $data = array('output' => $data, 'options' => $options);

        return $this->_engine->save($id, $data, $lifetime);
    }

    /**
     * Generate cache key by Uri
     *
     * @param string $uri
     */
    /*public function getCacheKeyByUri($uri, $prefix = null)
    {
        $uri = str_replace('_', '__', $uri);
        $uri = str_replace('/', '_', $uri);

        return $this->_generateId($uri, $prefix);
    }*/

    /**
     * Get cache key for current page
     *
     * @param boolean $useParams
     * @return string
     */
    /*public function getPageCacheKey($prefix = null)
    {
        $request = Vega_App::getInstance()->getRequest();

        $uri = $request->getRequestUrl();

        return $this->getCacheKeyByUri($uri, $prefix);
    }*/


    /**
     * Load page cache output
     *
     * @param Vega_Request $prefix
     * @return string
     */
    /*public function loadPageCache($outputOnly = true, $prefix = null)
    {
        return $this->load($this->getPageCacheKey($prefix), $outputOnly);
    }*/

    /**
     * Start page caching
     *
     * @param Vega_Request $request
     * @param string $prefix
     * @param Vega_View $view
     * @return mixed
     */
    public function startPageCache($url, $prefix = null, Vega_View $view = null)
    {
        require_once 'Vega/View.php';
        Vega_View::setGlobalCacheManager($this);

        $cache = $this->load($url, false, $prefix);
        if (!$cache)
        {
            // if there's no cache exists, skips
            return;
        }
        else
        {
            // if the cache is 'no layout'
            if (isset($cache['options']['no_layout']) && $cache['options']['no_layout'] == true)
            {
                if (null == $view)
                {
                    $view = new Vega_View(Vega_App::getInstance()->getLoader(), $prefix);
                }

                if (isset($cache['options']['layout_dir']))
                {
                    $view->setLayoutDir($cache['options']['layout_dir']);
                }

                if (isset($cache['options']['skin_name']))
                {
                    $view->setSkinName($cache['options']['skin_name']);
                }

                if (isset($cache['options']['layout_name']))
                {
                    $view->setLayoutName($cache['options']['layout_name']);
                }
                $output = $view->renderLayout($cache['output']);
            }
            else
            {
                // in case the cache is a complete page
                // because we have the PHP GC, so don't worry about memory double
                $output = $cache['output'];
            }

            ob_start();
            echo $output;
            ob_end_flush();
            exit;
        }
    }

    /**
     * Is a cache expired?
     *
     * @param string $name
     * @param integer $lifetime
     * @param mixed $prefix
     * @return boolean
     */
    public function isExpired($name, $lifetime, $prefix = null)
    {
        $id = $this->_generateId($name, $prefix);
        return $this->_engine->isExpired($id);
    }


    /**
     * Log write operator
     *
     * @param unknown_type $name
     * @param unknown_type $id
     * @param unknown_type $lifetime
     * @param unknown_type $strlen
     */
    public function log($name, $id, $lifetime, $strlen)
    {
        $this->_logs[] = array(
            'name'    => $name,
            'id'       => $id,
            'lifetime' => $lifetime,
            'lenght'   => $strlen
        );
    }

    public function getLogs()
    {
        return $this->_logs;
    }
}
